package com.mytool.service.impl;

import com.mytool.model.DDLGeneratorInput;
import com.mytool.model.GeneratedCodeResult;
import com.mytool.model.TableMetaData;
import com.mytool.service.DDLGeneratorService;
import com.mytool.util.TemplateEngineService;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * 基于Freemarker的DDL生成器服务实现，支持多表
 */
@Service
@Primary
public class FreemarkerDDLGeneratorServiceImpl implements DDLGeneratorService {

    @Autowired
    private DDLParser ddlParser;
    
    @Autowired
    private TemplateEngineService templateEngine;
    
    @Autowired
    private CodeStructureGenerator structureGenerator;
    
    @Autowired
    private FilepathResolver filepathResolver;
    
    // 模板文件列表
    private static final Map<String, String> TEMPLATE_FILES = new HashMap<>();
    
    // 测试模板文件列表
    private static final Map<String, String> TEST_TEMPLATE_FILES = new HashMap<>();
    
    static {
        // 定义需要生成的文件和对应的模板
        // Spring Boot 3.3.0架构
        TEMPLATE_FILES.put("entity", "springboot-templates/entity.ftl");
        TEMPLATE_FILES.put("repository", "springboot-templates/repository.ftl");
        TEMPLATE_FILES.put("service", "springboot-templates/service.ftl");
        TEMPLATE_FILES.put("serviceImpl", "springboot-templates/serviceImpl.ftl");
        TEMPLATE_FILES.put("controller", "springboot-templates/controller.ftl");
        
        // COLA架构相关模板
        TEMPLATE_FILES.put("domain-entity", "cola-templates/domain-entity.ftl");
        TEMPLATE_FILES.put("data-object", "cola-templates/data-object.ftl");
        TEMPLATE_FILES.put("dto", "cola-templates/dto.ftl");
        TEMPLATE_FILES.put("add-command", "cola-templates/add-command.ftl");
        TEMPLATE_FILES.put("modify-command", "cola-templates/modify-command.ftl");
        TEMPLATE_FILES.put("get-query", "cola-templates/get-query.ftl");
        TEMPLATE_FILES.put("list-query", "cola-templates/list-query.ftl");
        TEMPLATE_FILES.put("gateway", "cola-templates/gateway.ftl");
        TEMPLATE_FILES.put("service-interface", "cola-templates/service-interface.ftl");
        TEMPLATE_FILES.put("service-impl", "cola-templates/service-impl.ftl");
        TEMPLATE_FILES.put("repository-interface", "cola-templates/repository-interface.ftl");
        TEMPLATE_FILES.put("repository-impl", "cola-templates/repository-impl.ftl");
        TEMPLATE_FILES.put("domain-converter", "cola-templates/domain-converter.ftl");
        TEMPLATE_FILES.put("mapper", "cola-templates/mapper.ftl");
        TEMPLATE_FILES.put("mapper-xml", "cola-templates/mapper-xml.ftl");
        TEMPLATE_FILES.put("add-cmd-exe", "cola-templates/add-cmd-exe.ftl");
        TEMPLATE_FILES.put("modify-cmd-exe", "cola-templates/modify-cmd-exe.ftl");
        TEMPLATE_FILES.put("get-qry-exe", "cola-templates/get-qry-exe.ftl");
        TEMPLATE_FILES.put("list-qry-exe", "cola-templates/list-qry-exe.ftl");
        TEMPLATE_FILES.put("assembler", "cola-templates/assembler.ftl");
        TEMPLATE_FILES.put("domain-event", "cola-templates/domain-event.ftl");
        TEMPLATE_FILES.put("value-object", "cola-templates/value-object.ftl");
        TEMPLATE_FILES.put("domain-service", "cola-templates/domain-service.ftl");
        TEMPLATE_FILES.put("adapter", "cola-templates/adapter.ftl");
        TEMPLATE_FILES.put("external-dto", "cola-templates/external-dto.ftl");
        TEMPLATE_FILES.put("domain-event-publisher", "cola-templates/domain-event-publisher.ftl");
        TEMPLATE_FILES.put("external-system-exception", "cola-templates/external-system-exception.ftl");
        
        // 测试相关模板
        TEST_TEMPLATE_FILES.put("controller-test", "cola-templates/test/controller-test.ftl");
        TEST_TEMPLATE_FILES.put("service-test", "cola-templates/test/service-test.ftl");
        TEST_TEMPLATE_FILES.put("repository-test", "cola-templates/test/repository-test.ftl");
        TEST_TEMPLATE_FILES.put("mapper-test", "cola-templates/test/mapper-test.ftl");
    }
    
    @Override
    public GeneratedCodeResult generateColaCode(DDLGeneratorInput input) {
        GeneratedCodeResult result = new GeneratedCodeResult();
        
        try {
            // 解析多个表的DDL
            List<TableMetaData> tableMetaDataList = ddlParser.parseMultiTableDDL(input.getDdlSql());
            
            if (tableMetaDataList.isEmpty()) {
                result.setSuccess(false);
                result.setErrorMessage("未能从DDL中解析到任何表定义");
                return result;
            }
            
            // 保存表元数据列表到结果对象
            result.setTableMetaDataList(tableMetaDataList);
            
            // 生成所有表的代码
            Map<String, String> allGeneratedFiles = new HashMap<>();
            List<String> allProjectStructure = new ArrayList<>();
            
            // 为每个表生成代码
            for (TableMetaData tableMetaData : tableMetaDataList) {
                // 准备数据模型
                Map<String, Object> dataModel = prepareDataModel(input, tableMetaData);
                
                // 生成当前表的代码
                Map<String, String> tableFiles = generateFiles(dataModel, input);
                allGeneratedFiles.putAll(tableFiles);
                
                // 生成当前表的项目结构
                List<String> tableStructure = structureGenerator.generateProjectStructure(
                    input.getPackagePrefix(), 
                    tableMetaData, 
                    input.isGenerateTests(), 
                    input.getFrameworkType()
                );
                
                // 仅在第一次添加全局结构
                if (allProjectStructure.isEmpty()) {
                    allProjectStructure.addAll(tableStructure);
                } else {
                    // 只添加表特定的结构行
                    for (String line : tableStructure) {
                        if (line.contains(tableMetaData.getTableName()) || 
                            line.contains(tableMetaData.getDomainObjectName())) {
                            allProjectStructure.add(line);
                        }
                    }
                }
            }
            
            // 设置结果
            result.setSuccess(true);
            result.setGeneratedFiles(allGeneratedFiles);
            result.setProjectStructure(allProjectStructure);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorMessage("生成代码失败: " + e.getMessage());
            e.printStackTrace();
        }
        
        return result;
    }
    
    /**
     * 准备数据模型
     */
    private Map<String, Object> prepareDataModel(DDLGeneratorInput input, TableMetaData tableMetaData) {
        Map<String, Object> dataModel = new HashMap<>();
        String packagePrefix = input.getPackagePrefix();
        if (packagePrefix != null && !packagePrefix.startsWith("com.")) {
            packagePrefix = "com." + packagePrefix;
        }
        
        // 基本信息
        dataModel.put("packagePrefix", packagePrefix);
        dataModel.put("tableName", tableMetaData.getTableName());
        dataModel.put("domainObjectName", tableMetaData.getDomainObjectName());
        
        // 表信息
        dataModel.put("entityComment", tableMetaData.getTableComment().isEmpty() ? 
                tableMetaData.getDomainObjectName() : tableMetaData.getTableComment());
        dataModel.put("fields", tableMetaData.getFields());
        dataModel.put("hasDateFields", tableMetaData.isHasDateFields());
        dataModel.put("hasDecimalFields", tableMetaData.isHasDecimalFields());
        dataModel.put("hasStatusField", tableMetaData.isHasStatusField());
        
        // 生成选项
        dataModel.put("generateSwagger", input.isGenerateSwagger());
        dataModel.put("generateComments", input.isGenerateComments());
        dataModel.put("specialRequirements", input.getSpecialRequirements());
        
        return dataModel;
    }
    
    /**
     * 生成文件
     */
    private Map<String, String> generateFiles(Map<String, Object> dataModel, DDLGeneratorInput input) throws IOException, TemplateException {
        Map<String, String> generatedFiles = new HashMap<>();
        String packagePrefix = (String) dataModel.get("packagePrefix");
        String domainObjectName = (String) dataModel.get("domainObjectName");
        String tableName = (String) dataModel.get("tableName");
        String frameworkType = input.getFrameworkType();
        
        // 根据框架类型生成代码
        if ("SPRING_BOOT".equals(frameworkType)) {
            // 生成Spring Boot 3.3.0架构代码
            List<String> springBootTemplates = Arrays.asList(
                "entity", "repository", "service", "serviceImpl", "controller"
            );
            
            for (String key : springBootTemplates) {
                String templateFile = TEMPLATE_FILES.get(key);
                
                // 生成文件内容
                String fileContent = templateEngine.processTemplate(templateFile, dataModel);
                
                // 确定文件路径
                String filePath = filepathResolver.getFilePath(key, packagePrefix, domainObjectName, tableName);
                
                // 跳过不需要生成的文件
                if (filePath == null) {
                    continue;
                }
                
                // 添加到结果
                generatedFiles.put(filePath, fileContent);
            }
        } else {
            // 生成COLA架构代码
            for (Map.Entry<String, String> entry : TEMPLATE_FILES.entrySet()) {
                String key = entry.getKey();
                // 排除Spring Boot专用模板
                if (Arrays.asList("entity", "repository", "service", "serviceImpl").contains(key)) {
                    continue;
                }
                
                String templateFile = entry.getValue();
                
                // 生成文件内容
                String fileContent = templateEngine.processTemplate(templateFile, dataModel);
                
                // 确定文件路径
                String filePath = filepathResolver.getFilePath(key, packagePrefix, domainObjectName, tableName);
                
                // 跳过不需要生成的文件
                if (filePath == null) {
                    continue;
                }
                
                // 添加到结果
                generatedFiles.put(filePath, fileContent);
            }
        }
        
        // 如果需要生成测试代码
        if (input.isGenerateTests()) {
            for (Map.Entry<String, String> entry : TEST_TEMPLATE_FILES.entrySet()) {
                String key = entry.getKey();
                String templateFile = entry.getValue();
                
                // 生成文件内容
                String fileContent = templateEngine.processTemplate(templateFile, dataModel);
                
                // 确定测试文件路径
                String filePath = filepathResolver.getTestFilePath(key, packagePrefix, domainObjectName, tableName);
                
                // 跳过不需要生成的文件
                if (filePath == null) {
                    continue;
                }
                
                // 添加到结果
                generatedFiles.put(filePath, fileContent);
            }
        }
        
        return generatedFiles;
    }
} 